import { GameConfig } from "../configs/GameConfig";
import { Constants } from "../etc/Constants";

export enum EnumBagItemGrid {
    // 武器
    weapon = 0,
    // 击杀特效
    killEffect = 1,
    // 技能
    skill = 2,
    // 聊天气泡
    chatBubble = 3,
    // 背包开始
    itemStart = 100,
    // 背包结束
    itemEnd = 600,
}

export enum EnumItemType{
    // 武器
    weapon = 0,
    // 击杀特效
    killEffect = 1,
    // 物品
    item = 2,
    // 技能
    sk = 3,
    // 聊天气泡
    chatBubble = 5,
}

export interface ItemBaseInfo {
    // 物品表ID
    cfgID: number;
    // 数量
    count: number;
}

export class ItemValueObject {
    baseInfo: ItemBaseInfo;
    constructor(cfgID: number, count: number) {
        this.baseInfo = { cfgID: cfgID, count: count };
    }
}

export class ItemModuleData extends Subdata {
    @Decorator.persistence()
    bagContainer: { [grid: number]: ItemValueObject };

    get dataName(): string { return 'ItemModuleData' }

    protected initDefaultData() {
        this.setInitItem();
        this.save(true);
    }

    getItemByGrid(grid: number): ItemValueObject | undefined {
        return this.bagContainer[grid];
    }

    setItem(grid: number, itemVo: ItemValueObject) {
        this.bagContainer[grid] = itemVo;
    }

    // 原始方法, 不要直接调用, 通过itemModule调用
    addItem(itemID: number, count: number): boolean {
        let emptyGrid = this.getBagEmptyGrid();
        // 背包满了
        if (emptyGrid == -1) return false;

        // 背包有空格
        let itemCfg = GameConfig.Item.getElement(itemID);
        // 可堆叠
        if (itemCfg.Stack) {
            let grid = this.getBagItemGridByItemID(itemID);
            // 背包里有
            if (grid != -1) {
                this.bagContainer[grid].baseInfo.count += count;
            }
            // 没有
            else {
                this.bagContainer[emptyGrid] = new ItemValueObject(itemID, count);
            }
            return true;
        }

        // 没有足够的空格子
        let emptyCount = this.getBagEmptyGridCount();
        if (emptyCount < count) return false;

        // 一个一个添加
        for (let i = 0; i < count; i++) {
            let emptyGridIteration = this.getBagEmptyGrid();
            this.bagContainer[emptyGridIteration] = new ItemValueObject(itemID, 1);
        }
        return true;
    }

    // 原始方法, 不要直接调用, 通过itemModule调用
    // 删除给定数量的Item,无数量判断,需要在调用前判断物品剩余数量
    reduceItem(itemID: number, count: number) {
        for (let grid in this.bagContainer) {
            let itemVo = this.bagContainer[grid];

            if (count == 0) return; // 删完了

            if (itemVo.baseInfo.cfgID != itemID) continue; // 跳过

            // 数量够 直接删
            if (itemVo.baseInfo.count > count) {
                itemVo.baseInfo.count -= count;
                return;
            }

            // 数量等于,删除该格子的物品
            if (itemVo.baseInfo.count <= count) {
                this.deleteGridItem(Number(grid));
                count -= itemVo.baseInfo.count;
            }
        }
    }

    // 交换两个格子的物品
    replaceItem(source: number, destination: number) {
        let sourceItem = this.getItemByGrid(source);
        if (!sourceItem) return;

        let destinationGrid = this.getItemByGrid(destination);
        // 目标格子为空(直接移动)
        if (!destinationGrid) {
            this.setItem(destination, sourceItem);
            this.deleteGridItem(source);
        }
        // 交换
        else {
            this.setItem(source, this.getItemByGrid(destination));
            this.setItem(destination, sourceItem);
        }
    }

    // 根据格子删除物品
    reduceItemByGrid(grid: number, count: number) {
        let gridItems = this.bagContainer[grid];
        if (!gridItems) {
            console.error(`物品删除错误!grid:${grid}`);
            return;
        }
        if (gridItems.baseInfo.count < count) {
            console.error(`物品数量不足错误!grid:${grid}`);
            return;
        }

        if (gridItems.baseInfo.count == count) {
            this.deleteGridItem(grid);
        } else {
            this.bagContainer[grid].baseInfo.count -= count;
        }
    }

    // 删除格子上的物品
    deleteGridItem(grid: number) {
        delete this.bagContainer[grid];
    }

    // 获取背包内空格子的数量
    getBagEmptyGridCount(): number {
        // 来自白嘉航的小技巧❤
        return EnumBagItemGrid.itemEnd - EnumBagItemGrid.itemStart - Object.keys(this.bagContainer).length;
    }

    // 遍历背包全部格子(包括空格子)
    eachBag(action: (grid: number, item: ItemValueObject | undefined) => void) {
        for (let grid in this.bagContainer) {
            this.bagContainer[grid];
            action(Number(grid), this.bagContainer[grid]);
        }
    }

    // 遍历背包全部物品(包括不空格子)
    eachBagItem(action: (grid: number, item: ItemValueObject) => void) {
        for (let i = EnumBagItemGrid.itemStart; i <= EnumBagItemGrid.itemEnd; i++) {
            if (this.bagContainer[i]) {
                action(i, this.bagContainer[i]);
            }
        }
    }

    // 根据itemID获取item数量
    getItemCountByID(itemID: number): number {
        let count = 0;
        for (let grid in this.bagContainer) {
            let item = this.bagContainer[grid];
            if (item.baseInfo.cfgID != itemID) continue;

            count += item.baseInfo.count;
        }
        return count;
    }

    // 获取物品ID所在的格子
    getBagItemGridByItemID(itemID: number): number {
        for (let grid = EnumBagItemGrid.itemStart; grid <= EnumBagItemGrid.itemEnd; grid++) {
            if (!this.bagContainer[grid]) continue;
            if (this.bagContainer[grid].baseInfo.cfgID == itemID) return grid;

        }
        return -1;
    }

    // 返回第一个空格的索引,如果没有则返回-1
    getBagEmptyGrid(): number {
        for (let i = EnumBagItemGrid.itemStart; i <= EnumBagItemGrid.itemEnd; i++) {
            if (!this.bagContainer[i]) return i;
        }
        return -1;
    }

    // 计算物品数组需要的格子数量
    itemsNeedGridCount(items: ItemBaseInfo[]): number {
        let count = 0;
        for (let item of items) {
            let itemCfg = GameConfig.Item.getElement(item.cfgID);
            // 可堆叠
            if (itemCfg.Stack) {
                // 并且背包内有这个物品(不占格子)
                if (this.getBagItemGridByItemID(item.cfgID) != -1) continue;
                // 背包内没有这个物品(占一个格子)
                count++;
                continue;
            }
            // 不可堆叠
            count++;
        }
        return count;
    }
    
    // 玩家初始装备
    private setInitItem() {
        this.bagContainer = {};
        for (const cfg of GameConfig.InitialItems.getAllElement()) {
            let itemCfg = GameConfig.Item.getElement(cfg.ItemID);
            if (!itemCfg) {
                console.error("背包初始物品配置的物品ID不在物品表里!!!!");
                continue;
            }
            // 指定位置
            this.bagContainer[cfg.Grid] = new ItemValueObject(cfg.ItemID, 1);
        }
    }
}

export class ItemModuleC extends ModuleC<ItemModuleS, ItemModuleData> {

    protected onStart(): void {
        
    }

    send_equip(cfgID:number){
        this.server.net_equip_item(cfgID)
    }
    
    // 增加物品
    net_on_player_item_increase(items: ItemBaseInfo[]) {
        console.log("物品增加事件");
        SoundService.playSound(Constants.SoundGuid.GetItem);
    }
}

export class ItemModuleS extends ModuleS<ItemModuleC, ItemModuleData> {
    onPlayerAppearanceChanged:Action1<number> = new Action1()

    protected onPlayerEnterGame(player: mw.Player): void {
        let data = this.getPlayerData(player)
        data.eachBag((grid, itemVo)=>{
            let cfg = GameConfig.Item.getElement(itemVo.baseInfo.cfgID)
            if(!cfg){
                data.deleteGridItem(grid)
                data.save(true)
            }
        })

        if(!data.getItemByGrid(EnumBagItemGrid.chatBubble)){
            //如果没有东西,要给默认的
            let defaultChatBubbleId = GameConfig.InitialItems.findElement('Grid', EnumBagItemGrid.chatBubble).ItemID;
            let grid = data.getBagItemGridByItemID(defaultChatBubbleId);
            if(grid == -1){
                //没有默认
                this.addItems(player.playerId, [{cfgID:defaultChatBubbleId, count:1}]);
            }
            this.equipItem(player.playerId, defaultChatBubbleId);
        }
    }

    net_equip_item(itemID:number){
        this.equipItem(this.currentPlayerId, itemID)
    }

    equipItem(playerID: number, itemID: number) {
        let player = Player.getPlayer(playerID)
        if (!player) return

        let itemData = this.getPlayerData(playerID)
        let itemGrid = itemData.getBagItemGridByItemID(itemID)
        // 没有这个物品
        if (itemGrid == -1) return

        let itemCfg = GameConfig.Item.getElement(itemID)
        this.replaceItem(player, itemGrid, itemCfg.TargetGrid)
        this.onPlayerAppearanceChanged.call(playerID)
    }

    addItems(playerID: number, itemArray: ItemBaseInfo[]) {
        if (!Player.getPlayer(playerID)) return;
        // 判断是否够
        let data = this.getPlayerData(playerID);
        let needGridCount = data.itemsNeedGridCount(itemArray);
        
        if (needGridCount > data.getBagEmptyGridCount()) {
            console.error(`逻辑错误！, 未判断背包格子数就添加物品`);
            return;
        }

        for (let itemInfo of itemArray) {
            data.addItem(itemInfo.cfgID, itemInfo.count);
        }

        data.save(true);
        this.getClient(playerID).net_on_player_item_increase(itemArray);
        // vip 会更新appearance
        this.onPlayerAppearanceChanged.call(playerID)
    }
    
    reduceItem(playerID: number, itemID: number, count: number) {
        // 判断是否够
        let data = this.getPlayerData(playerID);

        if (data.getItemCountByID(itemID) < count) {
            console.error(`逻辑错误！, 未判断背包格子数就添加物品`);
            return;
        }

        data.reduceItem(itemID, count);
        data.save(true);
    }
    
    // 交换两个格子的物品
    replaceItem(player: mw.Player, source: number, destination: number) {
        let bag = DataCenterS.getData(player, ItemModuleData);

        let sourceItem = bag.getItemByGrid(source);
        if (!sourceItem) return;

        let destinationGrid = bag.getItemByGrid(destination);
        // 目标格子为空(直接移动)
        if (!destinationGrid) {
            bag.setItem(destination, sourceItem);
            bag.deleteGridItem(source);
        }
        // 交换
        else {
            bag.setItem(source, bag.getItemByGrid(destination));
            bag.setItem(destination, sourceItem);
        }
        bag.save(true)
    }
}